Skip to content

[DRAFT - held on OSv fork/COW landing] postgres18-musl: stock PostgreSQL 18 on OSv demo - #73

Draft
gburd wants to merge 3 commits into
cloudius-systems:masterfrom
gburd:wip/postgres18-musl-demo
Draft

[DRAFT - held on OSv fork/COW landing] postgres18-musl: stock PostgreSQL 18 on OSv demo#73
gburd wants to merge 3 commits into
cloudius-systems:masterfrom
gburd:wip/postgres18-musl-demo

Conversation

@gburd

@gburd gburd commented Jul 28, 2026

Copy link
Copy Markdown

Draft — held on the OSv fork/COW work landing on OSv master

Adds a postgres18-musl/ demo app that runs stock, unmodified PostgreSQL 18
(musl build) on OSv.

This will NOT run on stock OSv master. It requires the OSv-side
thread-backed fork() + per-child COW address space + per-process signals + the
fork-completeness stack (AS-aware mmap, fd inheritance, timer parking, cross-AS
coherence) to be present on OSv master first. Until then this is filed as a
draft so the app is visible alongside the kernel work it depends on.

Requires (on OSv, not this repo)

All of the above are opt-in / CONF_fork on OSv; PG-per-backend fork is the
whole reason this app needs them.

Status

Ready to draft; held on fork-merge. Do not merge until the OSv fork/COW
stack (#1455/#1456/#1457 + #1458) is on OSv master; add ZFS (#1423) for the
ZFS-on-NVMe /data variant.

gburd added 3 commits July 27, 2026 08:11
Builds PostgreSQL 18 (REL_18_STABLE) from source with musl-gcc as an OSv PIE,
boots a small baked cluster, and serves SQL over TCP. Single-backend demo;
requires the OSv fork/COW coherence work (conf_fork=1 + the fork-arena kernel
fixes) which is not yet on OSv master, so this stays a WIP branch until that
lands.
…ady-serving)

Add a documented full-VM snapshot/restore capability to the demo: boot
OSv+PostgreSQL under Firecracker to "ready to accept connections", take a Full
snapshot (guest memory + device/vCPU state), and on later launches restore that
snapshot so PostgreSQL is already serving. No reboot, no re-initdb, no musl-PIE
re-mmap.

Measured on m5d.metal (Firecracker v1.7.0, OSv v0.57 PG18.4-musl + OpenZFS,
single-file ZFS pool recordsize=8k):
  cold launch    -> first external select 1 = 11.75 s
  restore        -> first external select 1 =  0.24 s  (median of 5, ~48x)
  FC resume itself                          =  0.05 s
The ~6.7 s PostgreSQL musl-PIE mmap+init is eliminated (baked into the snapshot).

OSv resumes cleanly with NO OSv kernel changes required (already
snapshot-ready). Proof it is a resume not a reboot: pg_postmaster_start_time()
after restore is the original pre-snapshot boot time. Disk consistency via a
fresh COW copy (cp --reflink=auto) of the pool at snapshot time so the guest
ARC/shared_buffers agree with disk. Honest gotchas documented: clock skew
(kvmclock re-syncs, ~50-85 ms stable offset, tolerated), virtio re-attach (host
tap+DNAT must pre-exist), RNG (no observed duplication, weak probe).

Files: fc-snapshot.sh (driver), fc-snap.py (Firecracker API helper), README
section with build/snapshot/restore steps, measured numbers, and gotchas.

Author: Greg Burd
Add a 'lifecycle' subcommand that proves a PERSISTENT WARM checkpoint: a first
warm restore (~0.2s to first query), insert rows in the restored session, then
FREEZE (a fresh Full snapshot plus a preserved ZFS backing file) followed by a
CLEAN Firecracker shutdown (the VM process exits entirely), and finally a
SECOND warm restore from the frozen state (~0.2s again). The table, its rows,
and the original pg_postmaster_start_time() all survive the
freeze/clean-shutdown/warm-restart cycle, so the instance identity and its data
are a durable resumable checkpoint.

Also add a scripted 'seed' subcommand (build the single-file ZFS pool and
cpiod-push an initdb'd cluster into it) with its cpio_push.py helper, and fix
the boot argument passing so the leading --rootfs is not mis-parsed by the
Firecracker driver argument parser.

Measured on m5d.metal with Firecracker v1.7 (4 GiB guest, single-file ZFS
pool): both warm launches were about 0.17s to first query and
pg_postmaster_start_time() stayed equal to the very first launch across every
freeze/thaw cycle.

Signed-off-by: Greg Burd <greg@burd.me>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant